//Copyright (c) 2012 Olof Wallentin  <olov.wallentin@gmail.com>

//This software is provided 'as-is', without any express or implied
//warranty. In no event will the authors be held liable for any damages
//arising from the use of this software.

//Permission is granted to anyone to use this software for any purpose,
//including commercial applications, and to alter it and redistribute it
//freely, subject to the following restrictions:

   //1. The origin of this software must not be misrepresented; you must not
   //claim that you wrote the original software. If you use this software
   //in a product, an acknowledgment in the product documentation would be
   //appreciated but is not required.

   //2. Altered source versions must be plainly marked as such, and must not be
   //misrepresented as being the original software.

   //3. This notice may not be removed or altered from any source
   //distribution.

#include <string>
#include <sstream>
#include "Box2D\Common\b2Math.h"
#include "SFML\System\Vector2.hpp"
#include "SFML\Graphics\Rect.hpp"
#include "..\Graphics\Rect.h"
#include "..\Math\Vector2.h"

namespace
{
	template <typename T> const std::string numberToString(const T);			// converts any given value to a std::string
	template <typename T> T stringToNumber(const std::string&);					// converts a std::string to any valid number
	bool stringToBool(const std::string&);										// converts a string into a bool
	b2Vec2 stringTob2Vec2(const std::string&, const char = 'x');				// converts a string into a b2Vec2. default specifier is 'x', any other specifier can be set
	sf::Vector2f stringToSfVec2f(const std::string&, const char = 'x');			// converts a string into a sf::Vector2f. default specifier is 'x', any other specifier can be set
	sf::Vector2i stringToSfVec2i(const std::string&, const char = 'x');			// converts a string into a sf::Vector2i. default specifier is 'x', any other specifier can be set
	sf::IntRect stringToSfIntRect(const std::string&, const char = 'x');		// converts a string into a sf::IntRect. default specifier is 'x', any other specifier can be set
	sf::FloatRect stringToSfFloatRect(const std::string&, const char = 'x');	// converts a string into a sf::IntRect. default specifier is 'x', any other specifier can be set
	vn::IntRect stringToVnIntRect(const std::string&, const char = 'x');
	vn::FloatRect stringToVnFloatRect(const std::string&, const char = 'x');
	vn::Vector2 stringToVnVector2(const std::string&, const char = 'x');
}

namespace
{
	template <typename T> const std::string numberToString(const T p_line)
	{
		std::stringstream stream;
		stream << p_line;
		return stream.str();
	}
}

namespace
{
	template <typename T> T stringToNumber(const std::string& p_line)
	{
		std::stringstream stream(p_line);
		T result;
		return stream >> result ? result : 0;
	}
}

namespace
{
	bool stringToBool(const std::string& p_line)
	{
		std::string temp = p_line;
		for (unsigned int i = 0; i < temp.length(); i++)
		{
			temp[i] = tolower(temp[i]);	// convert all characters to lower case, will make checking the string easier.
		}
		return (temp == "true") ? true : false;
	}
}

namespace
{
	b2Vec2 stringTob2Vec2(const std::string& p_line, const char p_id)
	{
		size_t find = p_line.find_first_of(p_id);
		std::string x = p_line.substr(0, find);
		std::string y = p_line.substr(x.length() + 1, p_line.length() - x.length());
		return b2Vec2(static_cast<float>(atof(x.c_str())), static_cast<float>(atof(y.c_str())));
	}
}

namespace
{
	sf::Vector2f stringToSfVec2f(const std::string& p_line, const char p_id)
	{
		size_t find = p_line.find_first_of(p_id);
		std::string x = p_line.substr(0, find);
		std::string y = p_line.substr(x.length() + 1, p_line.length() - x.length());
		return sf::Vector2f(static_cast<float>(atof(x.c_str())), static_cast<float>(atof(y.c_str())));
	}
}

namespace
{
	sf::Vector2i stringToSfVec2i(const std::string& p_line, const char p_id)
	{
		size_t find = p_line.find_first_of(p_id);
		std::string x = p_line.substr(0, find);
		std::string y = p_line.substr(x.length() + 1, p_line.length() - x.length());
		return sf::Vector2i(atoi(x.c_str()), atoi(y.c_str()));
	}
}

namespace
{
	sf::IntRect stringToSfIntRect(const std::string& p_line, const char p_id)
	{
		size_t find = p_line.find_first_of(p_id);
		size_t find2 = p_line.find(p_id, find + 1);
		size_t find3 = p_line.find(p_id, find2 + 1);
		std::string x = p_line.substr(0, find);
		std::string y = p_line.substr(find + 1, find2 - (find + 1));
		std::string w = p_line.substr(find2 + 1, find3 - (find2 + 1));
		std::string h = p_line.substr(find3 + 1, p_line.length() - find3);
		return sf::IntRect(atoi(x.c_str()), atoi(y.c_str()), atoi(w.c_str()), atoi(h.c_str()));
	}
}

namespace
{
	sf::FloatRect stringToSfFloatRect(const std::string& p_line, const char p_id)
	{
		size_t find = p_line.find_first_of(p_id);
		size_t find2 = p_line.find(p_id, find + 1);
		size_t find3 = p_line.find(p_id, find2 + 1);
		std::string x = p_line.substr(0, find);
		std::string y = p_line.substr(find + 1, find2 - (find + 1));
		std::string w = p_line.substr(find2 + 1, find3 - (find2 + 1));
		std::string h = p_line.substr(find3 + 1, p_line.length() - find3);
		return sf::FloatRect(static_cast<float>(atof(x.c_str())), static_cast<float>(atof(y.c_str())), static_cast<float>(atof(w.c_str())), static_cast<float>(atof(h.c_str())));
	}
}

namespace
{
	vn::IntRect stringToVnIntRect(const std::string& p_line, const char p_id)
	{
		size_t find = p_line.find_first_of(p_id);
		size_t find2 = p_line.find(p_id, find + 1);
		size_t find3 = p_line.find(p_id, find2 + 1);
		std::string x = p_line.substr(0, find);
		std::string y = p_line.substr(find + 1, find2 - (find + 1));
		std::string w = p_line.substr(find2 + 1, find3 - (find2 + 1));
		std::string h = p_line.substr(find3 + 1, p_line.length() - find3);
		return vn::IntRect(atoi(x.c_str()), atoi(y.c_str()), atoi(w.c_str()), atoi(h.c_str()));
	}
}

namespace
{
	vn::FloatRect stringToVnFloatRect(const std::string& p_line, const char p_id)
	{
		size_t find = p_line.find_first_of(p_id);
		size_t find2 = p_line.find(p_id, find + 1);
		size_t find3 = p_line.find(p_id, find2 + 1);
		std::string x = p_line.substr(0, find);
		std::string y = p_line.substr(find + 1, find2 - (find + 1));
		std::string w = p_line.substr(find2 + 1, find3 - (find2 + 1));
		std::string h = p_line.substr(find3 + 1, p_line.length() - find3);
		return vn::FloatRect(static_cast<float>(atof(x.c_str())), static_cast<float>(atof(y.c_str())), static_cast<float>(atof(w.c_str())), static_cast<float>(atof(h.c_str())));
	}
}

namespace
{
	vn::Vector2 stringToVnVector2(const std::string& p_line, const char p_id)
	{
		size_t find = p_line.find_first_of(p_id);
		std::string x = p_line.substr(0, find);
		std::string y = p_line.substr(x.length() + 1, p_line.length() - x.length());
		return vn::Vector2(static_cast<float>(atof(x.c_str())), static_cast<float>(atof(y.c_str())));
	}
}



